{
 "cells": [
  {
   "metadata": {
    "collapsed": true
   },
   "cell_type": "markdown",
   "source": [
    "ChatPromptTemplate是创建聊天消息列表的提示模板，它比普通PromptTemplate更适合处理多角色、多轮次对话场景。\n",
    "特点：\n",
    "    支持System/Human/AI等不同角色的消息模板\n",
    "    对话历史维护\n",
    "\n",
    "参数类型：列表参数格式是tuple类型(role:str content:str组合最常用)\n",
    "元组格式为：\n",
    "    (role: str | type, content: str | list[dict] | list[object])\n",
    "    其中role是：字符串(如\"system\"、\"human\"、\"ai\")"
   ],
   "id": "ba89588d786e3647"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "#### 提示词模板ChatPromptTemplate的使用\n",
    "    1、两种实例化方式：构造方法和from_messages()\n",
    "    2、调用提示词模板的几种方法：invoke()、format()、format_messages()、format_prompt()\n",
    "    3、更丰富的实例化参数类型\n",
    "    4、结合LLM\n",
    "    5、插入消息列表：MessagePlaceholder"
   ],
   "id": "e391ad23751700ad"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "##### 实例化方式-构造方法",
   "id": "f6db54f934e76ee3"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "\n",
    "# 更简洁的方式\n",
    "chat_prompt_template = ChatPromptTemplate(\n",
    "    [(\"system\", \"你是一个AI助手，你的名字叫{name}\"), (\"human\", \"我的问题是{question}\")],\n",
    "    # input_variables={\"name\", \"question\"}\n",
    ")\n",
    "\n",
    "response = chat_prompt_template.invoke(input={\"name\": \"小智\", \"question\": \"1+2*3=?\"})\n",
    "print(type(response))\n",
    "print(response)"
   ],
   "id": "30acfc64f5c1a2c",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "##### 实例化方式-from_messages()",
   "id": "a84547f7bca6c568"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "\n",
    "chat_prompt_template = ChatPromptTemplate.from_messages(\n",
    "    [(\"system\", \"你是一个AI助手，你的名字叫{name}\"), (\"human\", \"我的问题是{question}\")])\n",
    "\n",
    "response = chat_prompt_template.invoke(input={\"name\": \"小智\", \"question\": \"1+2*3=?\"})\n",
    "print(type(response))\n",
    "print(response)"
   ],
   "id": "9eb73540a90ff177",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "##### 调用提示词模板的几种方法：invoke()、format()、format_messages()、format_prompt()",
   "id": "1453b5d7fa9d15f4"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "\n",
    "chat_prompt_template = ChatPromptTemplate.from_messages(\n",
    "    [(\"system\", \"你是一个AI助手，你的名字叫{name}\"), (\"human\", \"我的问题是{question}\")])\n",
    "response = chat_prompt_template.format_prompt(name=\"小智\", question=\"1+2*3=?\")\n",
    "print(type(response))\n",
    "print(response)"
   ],
   "id": "59a4881f450a069",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "##### 更丰富的实例化参数类型\n",
    "    从调用上来讲，不管是使用构造方法，还是使用from_message()。参数都是多样的，可以是：\n",
    "    字符串类型、字典类型、消息类型、元组构成的列表"
   ],
   "id": "aa5a0058ac5f2a83"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "##### 插入消息列表：MessagePlaceholder\n",
    "    当你不确定消息提示模板使用什么角色，或希望在格式化过程中插入消息列表时，就需要使用MessagePlaceholder，负责在特定位置添加消息列表\n",
    "    使用场景：多轮对话系统存储历史消息及Agent的中间步骤处理此功能非常有用"
   ],
   "id": "3250ee35656668db"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
    "from langchain_core.messages import HumanMessage\n",
    "\n",
    "chat_prompt_template = ChatPromptTemplate.from_messages(\n",
    "    [(\"system\", \"你是一个AI助手，你的名字叫{name}\"), MessagesPlaceholder(\"msgs\")])\n",
    "\n",
    "prompt_value = chat_prompt_template.invoke({\"name\": \"小智\", \"msgs\": [HumanMessage(content=\"1+2*3=?\")]})\n",
    "print(prompt_value)"
   ],
   "id": "34077a2baf7ebda2",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "##### 存储对话历史记录",
   "id": "1e7639f4b43192cf"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
    "from langchain_core.messages import HumanMessage, AIMessage\n",
    "from langchain_openai import ChatOpenAI\n",
    "import os\n",
    "\n",
    "prompt = ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        (\"system\", \"You are a helpful assistant.\"),\n",
    "        MessagesPlaceholder(\"history\"),\n",
    "        (\"human\", \"{question}\")\n",
    "    ]\n",
    ")\n",
    "\n",
    "messages = prompt.format_messages(history=[HumanMessage(content=\"1+2*3=?\"), AIMessage(content=\"1+2*3=7\")],\n",
    "                                  question=\"我刚才的问题是什么?\")\n",
    "\n",
    "os.environ['OPENAI_BASE_URL'] = 'https://vip.apiyi.com/v1'\n",
    "os.environ['OPENAI_API_KEY'] = 'sk-xU64G4hXJ4L47ko3764958119dB245D2BdEcE528767dA1Da'\n",
    "\n",
    "chat_model = ChatOpenAI(model=\"gpt-4o-mini\")\n",
    "response = chat_model.invoke(messages)\n",
    "print(response.content)"
   ],
   "id": "6feedf75639def7e",
   "outputs": [],
   "execution_count": null
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
